//文本编辑器 演示文本区、复选框、菜单、快捷菜单等组件和字体类的使用方法
package Example6point5;

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class EditorJFrame extends JFrame implements ActionListener, MouseListener {
    private JComboBox<String> combox_name;
    protected JComboBox<Integer> combox_size;
    private JCheckBox[] checkbox;
    private JRadioButton[] radios;
    protected Color[] colors = {Color.red, Color.green, Color.blue};
    private String[] colorname = {"red", "green", "blue"};
    protected JTextArea text;
    protected JPopupMenu popumenu;
    protected JMenu[] menus;
    private JCheckBoxMenuItem[] cbmenuitem;
    protected JToolBar toolbar;

    public EditorJFrame() {
        super("文本编辑器");
        this.setSize(800, 600);
        this.setLocationRelativeTo(null);
        this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);

        this.toolbar = new JToolBar();
        this.getContentPane().add(this.toolbar, "North");
        GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
        String[] fontsName = ge.getAvailableFontFamilyNames();
        this.combox_name = new JComboBox<String>(fontsName);
        this.combox_name.addActionListener(this);
        this.toolbar.add(this.combox_name);

        Integer[] sizes = {20, 30, 40, 50, 60, 70};
        this.combox_size = new JComboBox<Integer>(sizes);
        this.combox_size.setEditable(true);
        this.combox_size.addActionListener(this);
        this.toolbar.add(this.combox_size);

        String[] stylestr = {"粗体", "斜体"};
        this.checkbox = new JCheckBox[stylestr.length];
        for (int i = 0; i < stylestr.length; i++) {
            this.toolbar.add(this.checkbox[i] = new JCheckBox(stylestr[i]));
            this.checkbox[i].addActionListener(this);
        }
        ButtonGroup bgroup_color = new ButtonGroup();
        this.radios = new JRadioButton[this.colorname.length];
        for (int i = 0; i < this.radios.length; i++) {
            this.radios[i] = new JRadioButton(this.colorname[i]);
            this.radios[i].setForeground(this.colors[i]);
            this.radios[i].addActionListener(this);
            bgroup_color.add(this.radios[i]);
            this.toolbar.add(this.radios[i]);
        }
        this.radios[0].setSelected(true);

        JButton bopen = new JButton("打开", new ImageIcon("open.gif"));
        bopen.addActionListener(this);
        this.toolbar.add(bopen);
        JButton bsave = new JButton("保存", new ImageIcon("save.gif"));
        bsave.addActionListener(this);
        this.toolbar.add(bsave);

        this.text = new JTextArea("welcome 欢迎");
        this.text.addMouseListener(this);
        this.getContentPane().add(new JScrollPane(this.text));
        this.text.setForeground(colors[0]);
        this.addMenu();
        this.setVisible(true);
    }

    private void addMenu() {
        String[] menustr = {"文件", "编辑", "插入", "格式", "工具", "窗口", "帮助"};
        String[][] menuitemstr = {{"新建", "打开", "保存", "另存为", "|", "退出"},
                {"撤销", "恢复", "|", "剪切", "复制", "粘贴", "|", "查找", "替换"},
                {"日期", "文本"},
                {"字体"},
                {"字数统计", "自动更正", "拼写检查"}, {}, {}};
        JMenuBar menubar = new JMenuBar();
        this.setJMenuBar(menubar);
        this.menus = new JMenu[menustr.length];
        JMenuItem[][] menuitems = new JMenuItem[menuitemstr.length][];
        for (int i = 0; i < menuitemstr.length; i++) {
            this.menus[i] = new JMenu(menustr[i]);
            menubar.add(this.menus[i]);
            menuitems[i] = new JMenuItem[menuitemstr[i].length];
            for (int j = 0; j < menuitemstr[i].length; j++) {
                if (menuitemstr[i][j].equals("|"))
                    this.menus[i].addSeparator();
                else {
                    menuitems[i][j] = new JMenuItem(menuitemstr[i][j]);
                    this.menus[i].add(menuitems[i][j]);
                    menuitems[i][j].addActionListener(this);
                }
            }
        }
        menuitems[0][1].setIcon(new ImageIcon("open.gif"));
        menuitems[0][2].setIcon(new ImageIcon("save.gif"));

        JMenu menu_style = new JMenu("字形");
        menus[3].add(menu_style);
        String[] stylestr = {"粗体", "斜体"};
        this.cbmenuitem = new JCheckBoxMenuItem[stylestr.length];
        for (int i = 0; i < stylestr.length; i++) {
            this.cbmenuitem[i] = new JCheckBoxMenuItem(stylestr[i]);
            menu_style.add(this.cbmenuitem[i]);
            this.cbmenuitem[i].addActionListener(this);
        }
        JMenu menu_color = new JMenu("颜色");
        menus[3].add(menu_color);
        ButtonGroup buttongroup = new ButtonGroup();
        for (int i = 0; i < this.colorname.length; i++) {
            JRadioButtonMenuItem rbmi = new JRadioButtonMenuItem(this.colorname[i]);
            buttongroup.add(rbmi);
            menu_color.add(rbmi);
            rbmi.setForeground(this.colors[i]);
            rbmi.addActionListener(this);
        }

        this.popumenu = new JPopupMenu();
        String[] menuitems_cut = {"剪切", "复制", "粘贴"};
        JMenuItem[] popmenuitem = new JMenuItem[menuitems_cut.length];
        for (int i = 0; i < popmenuitem.length; i++) {
            popmenuitem[i] = new JMenuItem(menuitems_cut[i]);
            this.popumenu.add(popmenuitem[i]);
            popmenuitem[i].addActionListener(this);
        }
        popmenuitem[0].setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_X, InputEvent.CTRL_MASK));
        this.text.add(this.popumenu);
    }

    @Override
    public void actionPerformed(ActionEvent event) {
        if (event.getSource() instanceof JRadioButton)
            this.text.setForeground(((JComponent) event.getSource()).getForeground());
        else if (event.getSource() instanceof JMenuItem) {
            switch (event.getActionCommand()) {
                case "退出":
                    if (JOptionPane.showConfirmDialog(this, "终止当前程序运行？", "确认",
                            JOptionPane.YES_NO_OPTION) == 0)
                        System.exit(0);
                case "剪切":
                    this.text.cut();
                    break;
                case "复制":
                    this.text.copy();
                    break;
                case "粘贴":
                    this.text.paste();
                    break;
            }
        } else if (event.getSource() instanceof JComboBox<?> || event.getSource() instanceof JCheckBox) {
            int size = 0;
            String fontname = (String) this.combox_name.getSelectedItem();
            Object obj = this.combox_size.getSelectedItem();
            if (obj != null) {
                try {
                    if (obj instanceof Integer)
                        size = ((Integer) obj).intValue();
                    else if (obj instanceof String)
                        size = Integer.parseInt((String) obj);
                    if (size < 20 || size > 200)
                        throw new Exception(size + "字号超出20~200范围。");
                    java.awt.Font font = this.text.getFont();
                    int style = font.getStyle();
                    switch (event.getActionCommand()) {
                        case "粗体":
                            style ^= 1;
                            break;
                        case "斜体":
                            style ^= 2;
                    }
                    this.text.setFont(new Font(fontname, style, size));
                    insert(this.combox_size, size);
                } catch (NumberFormatException ex) {
                    JOptionPane.showMessageDialog(this, ex.getMessage() + "不能转换成整数");
                } catch (Exception ex) {
                    JOptionPane.showMessageDialog(this, ex.toString());
                }
            }
        }
    }

    public <T extends Comparable<? super T>> void insert(JComboBox<T> combox, T x) {
        int begin = 0, end = combox.getItemCount() - 1, mid = end;
        while (begin <= end) {
            mid = (begin + end) / 2;
            if (x.compareTo(combox.getItemAt(mid)) == 0) return;
            if (x.compareTo(combox.getItemAt(mid)) < 0) end = mid - 1;
            else begin = mid + 1;
        }
        combox.insertItemAt(x, begin);
    }

    @Override
    public void mouseClicked(MouseEvent e) {
    }

    @Override
    public void mousePressed(MouseEvent e) {
    }

    @Override
    public void mouseReleased(MouseEvent e) {
    }

    @Override
    public void mouseEntered(MouseEvent e) {
    }

    @Override
    public void mouseExited(MouseEvent e) {
    }

    public static void main(String[] args) {
        new EditorJFrame();
    }
}
